package com.yc.api1;

import java.util.Scanner;

public class ExceptionDemo1 {
	
	public static void main1(String[] args) {
		
		// 数学异常
		// int a = 1 / 0;
		
		// 数组越界
		//int[] arr = new int[3];
		//System.out.println(arr[3]);
				
		// 空指针异常
		//String s = null;
		//System.out.println(s.length());
		
		// 类型转换异常 Class Cast Exception
		String a = "中国人";   
		Object o = a;   
		Integer b = (Integer)o;
		//String c = (String)o;
		System.out.println(b);
		
	}
	
	public void a() {
		System.out.println("====== a =======");
		b();
	}
	
	public void b() {
		System.out.println("====== b =======");
		try {
			int i = 1/ 0 ;	
		} catch (ArithmeticException e) {
			System.out.println("出现了数学计算异常:" + e.getMessage());
			// 手动打印 方法栈
			e.printStackTrace();
//			处理完成之后, 程序将回到正常流程
		}
		c();
	}

	public void c() {
		int[] arr = {};
		try {
			System.out.println(arr[0]);
		}catch(ArrayIndexOutOfBoundsException e) {
			// 不处理, 将异常抛出, 我处理不了, 交给别人(上层)去处理
			throw e;
		}
		System.out.println("====== c =======");
	}
	
	// 出现异常后, 异常后面的代码就不会执行了
	/*
	 *  jvm 会在主线程中打印出异常信息
	 *  1. 异常类型
	 *  2. 异常描述
	 *  3. 方法调用栈
	 *  
	 *  处理异常:
	 *  1. 现场处理 try + catch + finally
	 *  2. 抛出异常
	 */
	
	public static void main2(String[] args) {
		ExceptionDemo1 ed = new ExceptionDemo1();
		try {
			ed.a();
		}  catch (ArrayIndexOutOfBoundsException e) {
			System.out.println("我就是可以处理异常的人: " + e.getMessage());
		}
		System.out.println("程序正常执行结束");
	}

	public static void main3(String[] args) {
		// 屏幕输入对象
		Scanner sc = new Scanner(System.in);
		
//		catch 可以捕获多个异常, 1. 多个catch 2. 一个catch 捕获多个
		try {
			System.out.print("请输入: ");
			int i = sc.nextInt();
			if(i==1) {
				Object o = null;
				System.out.println(o.toString());
			} else if (i == 2) {
				throw new NumberFormatException("这是我创建的数字格式化异常!");
			}
		} catch(NullPointerException e) {
			System.out.println("空指針異常!");
		} catch(NumberFormatException e) {
			System.out.println(e.getMessage());
		} catch (ClassCastException | ArrayIndexOutOfBoundsException e) {
			System.out.println("直接输出异常信息: " + e.getMessage());
		} catch( IllegalArgumentException e) {
			// 父类亦可以处理子类异常
			// Unreachable catch block for NullPointerException. 
			// It is already handled by the catch block for Exception
			// catch父类异常只能写在catch子类异常的下面
			System.out.println("捕获 IllegalArgumentException !");
		} catch( RuntimeException e) {
			System.out.println("捕获 RuntimeException !");
		} catch( Exception e) {
			System.out.println("捕获 Exception !");
		} finally {
			// 不管try中程序是否出现异常, finally 内的代码都会执行
			// 一般用于关闭资源
			sc.close();
			System.out.println("关闭 sc");
		}
		
		System.out.println("程序结束");
		
		
	}
	
	public static void main4(String[] args) {
		
		ExceptionDemo1 ed = new ExceptionDemo1();
		Scanner sc = new Scanner(System.in);
		while(true) {
			try {
				System.out.print("请输入用户名: ");
				String name = sc.nextLine();
				System.out.print("请输入密码: ");
				String pwd = sc.nextLine();
				ed.login(name, pwd);
				// 没有异常则打开系统菜单
				ed.menu();
				// 主程序暂停
				sc.nextLine();
			} catch (MyException e) {
				// 捕获自定义的业务
				// e.printStackTrace();
				System.out.println(e.getMessage());
			}
		}
		
	}
	
	public void menu() {
		System.out.println("显示程序主菜单!");
	}
	
	// 登录的业务方法, 方法抛出编译器异常, 必须在方法签名中定义 throws, 运行时异常无需申明
	public void login(String name, String pwd) throws MyException {
		// isBlank 不包含有效字符(非空格)的字符串
		if(name == null || name.isBlank()) {
			throw new MyException("用户名不能为空!");
		}
		if(pwd == null || pwd.isBlank()) {
			throw new MyException("密码不能为空!");
		}
		if(pwd.length() < 6) {
			throw new MyException("密码长度必须大于等于6位!");
		}
		if(name.equals("张三") && pwd.equals("123456")) {
			System.out.println("登录成功!");
		} else {
			throw new MyException("用户名或密码错误!");
		}
	}

	///////////////////////////////////////////////////
		
	public static void main(String[] args) {
		XXBiz biz = new XXBiz();
		try {
			biz.去上课();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}


// 自定义业务异常
class MyException extends Exception{

	/**
	 *  序列化版本编号
	 */
	private static final long serialVersionUID = 1L;

	public MyException() {
		super();
		// TODO Auto-generated constructor stub
	}

	public MyException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
		super(message, cause, enableSuppression, writableStackTrace);
		// TODO Auto-generated constructor stub
	}

	public MyException(String message, Throwable cause) {
		super(message, cause);
		// TODO Auto-generated constructor stub
	}

	public MyException(String message) {
		super(message);
		// TODO Auto-generated constructor stub
	}

	public MyException(Throwable cause) {
		super(cause);
		// TODO Auto-generated constructor stub
	}
	
}

// 异常链
class XXBiz {
	
	void 去上课() throws Exception {
		try {
			坐公交车();
		} catch (MyException e) {
			// 异常转型 MyException => Exception
			throw new Exception("上课迟到!", e);
		}
	}
	
	void 坐公交车() throws MyException {
		try {
			加油();
		} catch (MyException e) {
			throw new MyException("车子开不动了!", e);
		}
	}
	
	void 加油() throws MyException {
		throw new MyException("加油站没油了");
	}
	
}

















